﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Collections;

namespace TaskEditor
{
    public partial class ZControlEle : UserControl
    {
        private ZElementFile zFile = new ZElementFile();
        private ZEditObj zTempSelectObj;
        public ZControlEle()
        {
            InitializeComponent();
            reload();
        }

        private void reload()
        {
            ZEditObj obj = new ZEditObj(zFile, null);
            obj.zLoad();
            listBox1.Items.Clear();
            listBox1.Items.AddRange(obj.zChilds.ToArray());
        }
        public void zSaveFile(string filename = null)
        {
            if (filename == null)
            {
                DialogResult dr = saveFileDialog1.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    filename = saveFileDialog1.FileName;

                }
                else
                {
                    return;
                }
            }
            zFile.save(filename);
            MessageBox.Show("保存成功.");
        }
        public void zLoadFile(string filename = null)
        {
            if (filename == null)
            {
                DialogResult dr = openFileDialog1.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    filename = openFileDialog1.FileName;

                }
                else
                {
                    return;
                }
            }
            zFile = new ZElementFile();
            zFile.load(filename);
            reload();
            MessageBox.Show("加载成功!");
        }

        private void zShowInEditor()
        {
            if (zTempSelectObj != null)
            {
                label1.Text = zTempSelectObj.ToString();
                textBox1.Text = null;
                if (zTempSelectObj.zChilds.Count == 0 && !zTempSelectObj.zValueType.IsArray && !zTempSelectObj.zValueType.Name.StartsWith("List"))
                {
                    textBox1.Text = zTempSelectObj.zValue + "";
                }
            }


        }
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox li = sender as ListBox;
            if (li.SelectedItem is ZEditObj obj)
            {
                obj.zLoad();
                listBox2.Items.Clear();
                listBox2.Items.AddRange(obj.zChilds.ToArray());
                listBox3.Items.Clear();
                listBox5.Items.Clear();
                zTempSelectObj = obj;
                zShowInEditor();
            }
        }
        private void listBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox li = sender as ListBox;
            if (li.SelectedItem is ZEditObj obj)
            {
                obj.zLoad();
                listBox3.Items.Clear();
                listBox3.Items.AddRange(obj.zChilds.ToArray());
                listBox5.Items.Clear();
                zTempSelectObj = obj;
                zShowInEditor();
            }

        }
        private void listBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox li = sender as ListBox;
            if (li.SelectedItem is ZEditObj obj)
            {
                obj.zLoad(9);
                listBox5.Items.Clear();
                listBox5.Items.AddRange(obj.zChilds.ToArray());
                zTempSelectObj = obj;
                zShowInEditor();
            }

        }
        private void listBox5_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox li = sender as ListBox;
            if (li.SelectedItem is ZEditObj obj)
            {
                zTempSelectObj = obj;
                zShowInEditor();
            }
        }
        private void listBox_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ListBox s = sender as ListBox;
            if (s.SelectedItem != null)
            {
                ZEditObj o = s.SelectedItem as ZEditObj;
                o.zDialogSetValue();
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (zTempSelectObj != null && zTempSelectObj.zAddNewArray())
            {
                zTempSelectObj.zLoad();
                listBox3.Items.Clear();
                listBox3.Items.AddRange(zTempSelectObj.zChilds.ToArray());
                listBox5.Items.Clear();
            }

        }
        private void button2_Click(object sender, EventArgs e)
        {
            if (zTempSelectObj != null && zTempSelectObj.zRemvoSelfFromArray())
            {
                zTempSelectObj.zParent.zLoad();
                zTempSelectObj = null;
                listBox3.Items.Clear();
                listBox3.Items.AddRange(zTempSelectObj.zParent.zChilds.ToArray());
                listBox5.Items.Clear();
            }
        }
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked && int.TryParse(textBox1.Text, out int v))
            {
                byte[] data = BitConverter.GetBytes(v);
                float fvalue = BitConverter.ToSingle(data, 0);
                textBox1.Text = fvalue + "";
            }
            else if (float.TryParse(textBox1.Text, out float f))
            {
                byte[] data = BitConverter.GetBytes(f);
                int fvalue = BitConverter.ToInt32(data, 0);
                textBox1.Text = fvalue + "";
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            object value = textBox1.Text;
            if (checkBox1.Checked && float.TryParse(textBox1.Text, out float v))
            {
                byte[] data = BitConverter.GetBytes(v);
                int fvalue = BitConverter.ToInt32(data, 0);
                value = fvalue;
            }
            zTempSelectObj.zSetFromStringValue(value+"");
            zTempSelectObj.zParent.zLoad(9);
            listBox5.Items.Clear();
            listBox5.Items.AddRange(zTempSelectObj.zParent.zChilds.ToArray());

        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (listBox2.SelectedItem is ZEditObj obj)
            {
                var s= obj.zChilds.FindAll(p => p.ToString().ToUpper().Contains(textBox2.Text.ToUpper()));
                listBox3.Items.Clear();
                listBox3.Items.AddRange(s.ToArray());
            }

        }
    }

    class ZEditObj
    {

        public ZEditObj zParent { get; }
        public object zValue { get; }
        public Type zValueType { get; }
        public List<ZEditObj> zChilds { get; }

        private int zListIndex = -1;
        private FieldInfo zFieldInfo;
        private IList zListValue;
        private string zDes;
        private int zInAll;
        public override string ToString()
        {
            return zDes;
        }
        public ZEditObj(object obj, ZEditObj parent)
        {
            zValue = obj;
            zChilds = new List<ZEditObj>();
            zParent = parent;
            zValueType = zValue.GetType();
            zDes = zDes + ":" + zValue;
        }
        public void zLoad(int inall = 1)
        {
            inall--;
            zInAll = inall;
            if (inall < 0)
            {
                return;
            }
            zChilds.Clear();
            Type t = zValue.GetType();
            if (t.Name.StartsWith("List") || t.IsArray)
            {
                Type arraytype = t.GetElementType();
                zListValue = zValue as IList;
                for (int i = 0; i < zListValue.Count; i++)
                {
                    object arrayvalue = zListValue[i];
                    if (arrayvalue == null)
                    {
                        arrayvalue = Activator.CreateInstance(arraytype);
                    }
                    ZEditObj o = new ZEditObj(arrayvalue, this)
                    {
                        zListIndex = i,
                    };
                    o.zDes = "[" + i + "]" + o.zDes;
                    zChilds.Add(o);
                    o.zLoad(zInAll);
                    zChilds.AddRange(o.zChilds);
                }
            }
            else if (t.Name == "ZMString")
            {
                zDes = zDes + ":" + zValue;
            }
            else if (!t.FullName.StartsWith("System"))
            {
                var fields = t.GetFields();
                foreach (var item in fields)
                {
                    ZEditObj o = new ZEditObj(item.GetValue(zValue), this)
                    {
                        zFieldInfo = item,
                    };
                    o.zDes = item.Name + o.zDes;
                    if (item.FieldType.Name.StartsWith("List") || item.FieldType.IsArray)
                    {
                        IList data = o.zValue as IList;
                        o.zDes = $"<{data.Count}>" + item.Name;
                    }
                    zChilds.Add(o);
                    o.zLoad(zInAll);
                    zChilds.AddRange(o.zChilds);
                }
            }

        }
        private object transLateType(string value, Type type)
        {
            switch (type.Name)
            {
                case "String":
                    return value;
                case "UInt16":
                    return ushort.Parse(value);
                case "UInt32":
                    return uint.Parse(value);
                case "Int32":
                    return int.Parse(value);
                case "Int16":
                    return ushort.Parse(value);
                case "Byte":
                    return byte.Parse(value);
                case "Single":
                    return float.Parse(value);
                case "Boolean":
                    return bool.Parse(value);
            }
            throw new Exception("不支持的转换:" + type.Name);
        }
        public void zDialogSetValue()
        {
            ZEditorForm zEditorForm = new ZEditorForm(zDes, zValue.ToString());
            if (zValue is ZMString ms)
            {
                DialogResult dr = zEditorForm.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    ms.zSetValue(zEditorForm.zValue);
                }
            }
            else if (zChilds.Count == 0)
            {
                DialogResult dr = zEditorForm.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    string value = zEditorForm.zValue;
                    if (zListIndex != -1)
                    {
                        zParent.zListValue[zListIndex] = transLateType(value, zValue.GetType());
                    }
                    else if (zFieldInfo != null)
                    {
                        zFieldInfo.SetValue(zParent.zValue, transLateType(value, zValue.GetType()));
                    }
                    zParent.zLoad(zParent.zInAll);
                }
            }

        }
        public void zSetFromStringValue(string value)
        {
            try
            {
                if (zValue is ZMString ms)
                {
                    ms.zSetValue(value);
                }
                else if (zChilds.Count == 0 && !zValueType.IsArray && !zValueType.Name.StartsWith("List"))
                {
                    if (zListIndex != -1)
                    {
                        zParent.zListValue[zListIndex] = transLateType(value, zValue.GetType());
                    }
                    else if (zFieldInfo != null)
                    {
                        zFieldInfo.SetValue(zParent.zValue, transLateType(value, zValue.GetType()));
                    }
                    zParent.zLoad(zParent.zInAll);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }

        }
        public bool zAddNewArray()
        {
            if (zListValue != null && !zListValue.IsFixedSize)
            {
                Type t = zListValue.GetType();
                if (t.HasElementType)
                {
                    t = t.GetElementType();
                }
                else
                {
                    t = t.GetGenericArguments()[0];
                }
                object v = Activator.CreateInstance(t);
                zListValue.Add(v);
                return true;
            }
            return false;
        }
        public bool zRemvoSelfFromArray()
        {
            if (zParent != null && zParent.zListValue != null && !zParent.zListValue.IsFixedSize && zListIndex < zParent.zListValue.Count)
            {
                zParent.zListValue.RemoveAt(zListIndex);
                return true;
            }
            return false;
        }
    }

}
